package cn.wj.school.server.net;

import cn.wj.school.server.net.ecode.MsgDecoder;
import cn.wj.school.server.net.ecode.MsgEncoder;
import cn.wj.school.server.net.handler.AcceptorIdleStateTrigger;
import cn.wj.school.server.net.handler.ServerChannelHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @Author: yueding
 * @Description:
 * @Date: Created in 17:11 2018/12/28
 * @Modified By: yueding Copyright(c) cai-inc.com
 */
@Slf4j
public class ServerNet {
    /**
     * 服务端监听的端口地址
     */
    private int portNumber = 7878;

    private final AcceptorIdleStateTrigger idleStateTrigger = new AcceptorIdleStateTrigger();

    public ServerNet(Integer port) {
        if (port != null) {
            this.portNumber = port;
        }
        start();
    }

    public void start() {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup);
            b.channel(NioServerSocketChannel.class);
            b.option(ChannelOption.SO_BACKLOG, 128);
            // 通过NoDelay禁用Nagle,使消息立即发出去，不用等待到一定的数据量才发出去
            b.option(ChannelOption.TCP_NODELAY, true);
            // 保持长连接状态
            b.childOption(ChannelOption.SO_KEEPALIVE, true);
            b.childHandler(new ChannelInitializer() {
                // 初始化channel
                @Override
                protected void initChannel(Channel ch) throws Exception {
                    ch.pipeline().addLast(new MsgDecoder(1024*4,0,4,0,4));
                    ch.pipeline().addLast(new LengthFieldPrepender(4));
                    ch.pipeline().addLast(new MsgEncoder());
                    // 10秒没数据
                    ch.pipeline().addLast(new IdleStateHandler(300, 0, 0, TimeUnit.SECONDS));
                    ch.pipeline().addLast(idleStateTrigger);
                    ch.pipeline().addLast(new ServerChannelHandler());
                }
            });

            // 服务器绑定端口监听
            ChannelFuture f = b.bind(portNumber).sync();
            log.info("============服务端启动!==========");
            // 监听服务器关闭监听
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
